package com.bonc.modules.business.service.impl;


import com.bonc.common.utils.ObjectUtil;
import com.bonc.common.utils.SftpConnectConfig;
import com.bonc.common.utils.UploadMonitorCallable;
import com.bonc.datasource.annotation.DataSource;
import com.bonc.modules.business.dao.TbWorkOederDistributionDao;
import com.bonc.modules.business.dao.TbWorkOrderReplyDao;
import com.bonc.modules.business.entity.TbWorkOederDistributionEntity;
import com.bonc.modules.business.service.FileSystemService;
import com.bonc.modules.business.service.TbWorkOederDistributionService;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

@DataSource("data")
@Slf4j
@Service("fileSystemService")
public class FileSystemServiceImpl implements FileSystemService {

    /*@Autowired
    @Qualifier("channelSftp")
    private ChannelSftp channelSftp;

    @Autowired
    @Qualifier("channelSftp1")
    private ChannelSftp channelSftp1;*/

    @Resource
    private TbWorkOederDistributionDao tbWorkOederDistributionDao;

    @Resource
    private TbWorkOrderReplyDao TbWorkOrderReplyDao;

    /**
     *
     * @param directory 服务器路径
     * @param sftpFileName 文件名称
     * @param inputStream 文件流
     * @return
     * @throws Exception*/


    @Override
    public String uploadFile(String directory, String sftpFileName, InputStream inputStream) throws Exception {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp = sftp.channelSftp();
        Calendar calendar= Calendar.getInstance();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateFormat1= new SimpleDateFormat("yyyyMMddHHmmss");
        String date = dateFormat.format(calendar.getTime());
        String ftptempfile = dateFormat1.format(calendar.getTime());
        int count = 0;
        List<Map<String,Object>> list = tbWorkOederDistributionDao.getCountfromOrderDistribution(date);
        for(int i=0;i<list.size();i++){
            String attachList = list.get(i).get("ATTACH_LIST").toString();
            String str[] = attachList.split("\\|");
            count = count + str.length;
        }
        System.out.println(count);
        int counts = count+1;
        String xlh = "";
        if(count < 10){
            xlh = "00" + counts;
        }else if(count < 100 && count > 10){
            xlh = "0" + counts;
        }else{
            xlh = counts+"";
        }

        //落地文件名
        String renturnName = "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+sftpFileName.substring(sftpFileName.lastIndexOf("."));
        String fileNameNew = directory + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+sftpFileName.substring(sftpFileName.lastIndexOf("."));
        //传输过程临时后缀名
        String filename = directory + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+sftpFileName.substring(sftpFileName.lastIndexOf("."))+"."+ftptempfile+"."+"file";

        String tempPath = "";
        try {
            if (!ObjectUtil.isEmptyObject(directory)) {
                directory = directory.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/"
                if (directory.startsWith("/")) {
                    tempPath += directory;
                } else {
                    if (ObjectUtil.isEmptyObject(tempPath)) {
                        tempPath = directory;
                    } else {
                        tempPath = tempPath + "/" + directory;
                    }
                }
            }
            //if(channelSftp.pwd().equals(""))
            tempPath = tempPath.substring(1,tempPath.length()-1);
            channelSftp.cd(tempPath);
        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String [] dirs= tempPath.split("/");
            String path = "";
            for(String dir : dirs){
                if(ObjectUtil.isEmptyObject(dir)) continue;
                if (tempPath.startsWith("/")) {
                    path += "/" + dir;
                } else  {
                    if (ObjectUtil.isEmptyObject(path)) {
                        path += dir;
                    } else {
                        path += "/" + dir;
                    }
                }
                try{
                    channelSftp.cd(path);
                }catch(SftpException ex){
                    channelSftp.mkdir(path);
                    channelSftp.cd(path);
                }
            }
        }
        UploadMonitorCallable monitor = new UploadMonitorCallable(inputStream.available());
        channelSftp.put(inputStream, filename, monitor);  //上传文件
        FutureTask<Integer> future = new FutureTask<>(monitor);
        new Thread(future).start();
        try {
            Integer flag=future.get();
            if(flag==1){//上传完成后修改文件名称

                channelSftp.rename(filename,fileNameNew);
                inputStream.close();
                //ZipCipherUtil.deleteFile(filePath+sftpFileName);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            this.disconnect(channelSftp);
        }
        return renturnName;
    }

    @Override
    public boolean uploadFile1(String directory, String sftpFileName, InputStream inputStream) throws Exception {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp1 = sftp.channelSftp1();

        //String filename = directory + sftpFileName;
        String tempPath = "";
        try {
            if (!ObjectUtil.isEmptyObject(directory)) {
                directory = directory.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/"
                if (directory.startsWith("/")) {
                    tempPath += directory;
                } else {
                    if (ObjectUtil.isEmptyObject(tempPath)) {
                        tempPath = directory;
                    } else {
                        tempPath = tempPath + "/" + directory;
                    }
                }
            }

            tempPath = tempPath.substring(1,tempPath.length()-1);
            channelSftp1.cd(tempPath);

        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String [] dirs= tempPath.split("/");
            String path = "";
            for(String dir : dirs){
                if(ObjectUtil.isEmptyObject(dir)) continue;
                if (tempPath.startsWith("/")) {
                    path += "/" + dir;
                } else  {
                    if (ObjectUtil.isEmptyObject(path)) {
                        path += dir;
                    } else {
                        path += "/" + dir;
                    }
                }
                channelSftp1.cd(path);
                try{
                    channelSftp1.cd(path);
                }catch(SftpException ex){
                    channelSftp1.mkdir(path);
                    channelSftp1.cd(path);
                }
            }
        }
        UploadMonitorCallable monitor = new UploadMonitorCallable(inputStream.available());
        channelSftp1.put(inputStream, sftpFileName, monitor);  //上传文件
        FutureTask<Integer> future = new FutureTask<>(monitor);
        new Thread(future).start();
        try {
            Integer flag=future.get();
            if(flag==1){//上传完成后修改文件名称
                //channelSftp1.rename(filename,filename);
                inputStream.close();
                //ZipCipherUtil.deleteFile(filePath+sftpFileName);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            this.disconnect(channelSftp1);
        }
        return true;
    }

    /**
     * 上传文件
     * @param targetPath 上传文件的服务器地址
     * @param file
     * @return
     * @throws Exception*/


    @Override
    @Async
    public String uploadFile(String targetPath, File file) throws Exception {
        FileInputStream fis=null;
        StringBuffer buffer = new StringBuffer();
        try {
            fis = new FileInputStream(file);
            InputStreamReader reader = new InputStreamReader(fis); //最后的"GBK"根据文件属性而定，如果不行，改成"UTF-8"试试
            BufferedReader br = new BufferedReader(reader);
            String line;
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
            br.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        InputStream is = new ByteArrayInputStream(buffer.toString().getBytes("UTF-8"));
        return this.uploadFile(targetPath,file.getName(), is);

        //return this.uploadFile(targetPath,file.getName(), new FileInputStream(file));
    }

    @Override
    public boolean uploadFile1(String targetPath, File file) throws Exception {
        FileInputStream fis=null;
        StringBuffer buffer = new StringBuffer();
        try {
            fis = new FileInputStream(file);
            InputStreamReader reader = new InputStreamReader(fis); //最后的"GBK"根据文件属性而定，如果不行，改成"UTF-8"试试
            BufferedReader br = new BufferedReader(reader);
            String line;
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
            br.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        InputStream is = new ByteArrayInputStream(buffer.toString().getBytes("UTF-8"));
        return this.uploadFile1(targetPath,file.getName(), is);
    }

    @Override
    public boolean uploadFile2(String remotePath, String remoteFileName, String localPath, String localFileName){
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp1 = sftp.channelSftp1();
        FileInputStream in = null;
        try
        {
            createDirs(remotePath,channelSftp1);

            File file = new File(localPath + localFileName);
            in = new FileInputStream(file);

            channelSftp1.put(in, remoteFileName);

            return true;
        }

        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SftpException e)
        {
            e.printStackTrace();
        }

        finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    @Override
    public String uploadFile3(String remotePath, String remoteFileName, String localPath, String localFileName,int flags){
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp = sftp.channelSftp();

        Calendar calendar= Calendar.getInstance();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateFormat1= new SimpleDateFormat("yyyyMMddHHmmss");
        String date = dateFormat.format(calendar.getTime());
        String ftptempfile = dateFormat1.format(calendar.getTime());

        int count = 0;
        List<Map<String,Object>> list = tbWorkOederDistributionDao.getCountfromOrderDistribution(date);
        for(int i=0;i<list.size();i++){
            String attachList = list.get(i).get("ATTACH_LIST").toString();
            String str[] = attachList.split("\\|");
            count = count + str.length;
        }

        int counts;
        if(flags == 0){
            counts = count+1;
        }else{
            counts = count + flags;
        }


        String xlh = "";
        if(count < 10){
            xlh = "00" + counts;
        }else if(count < 100 && count > 10){
            xlh = "0" + counts;
        }else{
            xlh = counts+"";
        }

        //落地文件名
        String renturnName = "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."));
        String fileNameNew = remotePath + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."));
        //传输过程临时后缀名
        String filename = remotePath + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."))+"."+ftptempfile+"."+"file";

        FileInputStream in = null;
        try
        {
            createDirs(remotePath,channelSftp);

            File file = new File(localPath + localFileName);
            in = new FileInputStream(file);

            UploadMonitorCallable monitor = new UploadMonitorCallable(in.available());
            channelSftp.put(in, filename, monitor);
            FutureTask<Integer> future = new FutureTask<>(monitor);

            new Thread(future).start();
            Integer flag=future.get();
            if(flag==1){//上传完成后修改文件名称

                channelSftp.rename(filename,fileNameNew);
                in.close();
                //ZipCipherUtil.deleteFile(filePath+sftpFileName);
            }

            return renturnName;
        }

        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SftpException e)
        {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return renturnName;
    }

    @Override
    public String uploadFile4(String remotePath, String remoteFileName, String localPath, String localFileName, int flags) {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp = sftp.channelSftp();

        Calendar calendar= Calendar.getInstance();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateFormat1= new SimpleDateFormat("yyyyMMddHHmmss");
        String date = dateFormat.format(calendar.getTime());
        String ftptempfile = dateFormat1.format(calendar.getTime());

        int count = 0;
        List<Map<String,Object>> list = TbWorkOrderReplyDao.getCountfromOrderReply(date);
        for(int i=0;i<list.size();i++){
            String attachList = list.get(i).get("ATTACH_LIST").toString();
            String str[] = attachList.split("\\|");
            count = count + str.length;
        }

        int counts;
        if(flags == 0){
            counts = count+1;
        }else{
            counts = count + flags;
        }


        String xlh = "";
        if(count < 10){
            xlh = "00" + counts;
        }else if(count < 100 && count > 10){
            xlh = "0" + counts;
        }else{
            xlh = counts+"";
        }

        //落地文件名
        String renturnName = "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."));
        String fileNameNew = remotePath + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."));
        //传输过程临时后缀名
        String filename = remotePath + "GZLSEND"+"_"+"1001"+"_"+"351"+"_"+date+"_"+xlh+remoteFileName.substring(remoteFileName.lastIndexOf("."))+"."+ftptempfile+"."+"file";

        FileInputStream in = null;
        try
        {
            createDirs(remotePath,channelSftp);

            File file = new File(localPath + localFileName);
            in = new FileInputStream(file);

            UploadMonitorCallable monitor = new UploadMonitorCallable(in.available());
            channelSftp.put(in, filename, monitor);
            FutureTask<Integer> future = new FutureTask<>(monitor);

            new Thread(future).start();
            Integer flag=future.get();
            if(flag==1){//上传完成后修改文件名称

                channelSftp.rename(filename,fileNameNew);
                in.close();
                //ZipCipherUtil.deleteFile(filePath+sftpFileName);
            }

            return renturnName;
        }

        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SftpException e)
        {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return renturnName;
    }

    /**
     * 下载文件
     * @param directory 下载文件的路径
     * @param downloadFile 文件
     * @param saveFile 本地保存路径
     * @return
     * @throws Exception*/


    @Override
    public boolean downloadFile(String directory, String downloadFile, String saveFile) throws Exception {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp = sftp.channelSftp();
        try {
            if (!ObjectUtil.isEmptyObject(directory)) {
                channelSftp.cd(directory);
            }
            saveFile = saveFile.replace("\\", File.separator);
            saveFile = saveFile + (saveFile.endsWith(File.separator) ? downloadFile : "/" + downloadFile);
            File file = new File(saveFile);
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            file = new File(saveFile);
            channelSftp.get(downloadFile, new FileOutputStream(file));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }finally {
            this.disconnect(channelSftp);
        }
    }

    //
    @Override
    public boolean downloadFile1(String directory, String downloadFile, String saveFile) throws Exception {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp1 = sftp.channelSftp1();
        try {
            if (!ObjectUtil.isEmptyObject(directory)) {
                channelSftp1.cd(directory);
            }
            saveFile = saveFile.replace("\\", File.separator);
            saveFile = saveFile + (saveFile.endsWith(File.separator) ? downloadFile : "/" + downloadFile);
            File file = new File(saveFile);
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            file = new File(saveFile);
            channelSftp1.get(downloadFile, new FileOutputStream(file));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }finally {
            this.disconnect(channelSftp1);
        }
    }

    /**
     * 删除文件
     * @param directory
     * @param targetPath
     * @return
     * @throws Exception*/


    @Override
    public boolean deleteFile(String directory, String targetPath) throws Exception {
        SftpConnectConfig sftp = new SftpConnectConfig();
        ChannelSftp channelSftp = sftp.channelSftp();
        try {
            channelSftp.cd(directory);
            channelSftp.rm(targetPath);
            return true;
        } catch (Exception e) {
            log.error("Delete file failure. TargetPath: {}", targetPath, e);
            throw new Exception("Delete File failure");
        } finally {
            this.disconnect(channelSftp);
        }
    }

    /**
     * 创建一级或者多级目录
     * @param dirPath
     * @param sftp
     * @return*/


    private boolean createDirs(String dirPath, ChannelSftp sftp) {
        if (dirPath != null && !dirPath.isEmpty()
                && sftp != null) {
            String[] dirs = Arrays.stream(dirPath.split("/"))
                    .filter(StringUtils::isNotBlank)
                    .toArray(String[]::new);

            for (String dir : dirs) {
                try {
                    sftp.cd(dir);
                    log.info("Change directory {}", dir);
                } catch (Exception e) {
                    try {
                        sftp.mkdir(dir);
                        log.info("Create directory {}", dir);
                    } catch (SftpException e1) {
                        log.error("Create directory failure, directory:{}", dir, e1);
                        e1.printStackTrace();
                    }
                    try {
                        sftp.cd(dir);
                        log.info("Change directory {}", dir);
                    } catch (SftpException e1) {
                        log.error("Change directory failure, directory:{}", dir, e1);
                        e1.printStackTrace();
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 创建session
     * @param jsch
     * @param host
     * @param username
     * @param port
     * @return
     * @throws Exception*/


    private Session createSession(JSch jsch, String host, String username, Integer port) throws Exception {
        Session session = null;

        if (port <= 0) {
            session = jsch.getSession(username, host);
        } else {
            session = jsch.getSession(username, host, port);
        }

        if (session == null) {
            throw new Exception(host + " session is null");
        }

        return session;
    }

    /**
     * 关闭连接
     * @param sftp*/


    private void disconnect(ChannelSftp sftp) {
        try {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                } else if (sftp.isClosed()) {
                    log.info("sftp is closed already");
                }
                if (null != sftp.getSession()) {
                    sftp.getSession().disconnect();
                }
            }
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }
}
